/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.moveclock.views;

// Need the following import to get access to the app resources, since this
// class is in a sub-package.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;


/**
 * Example of how to write a custom subclass of View. JoystickView
 * is used to draw simple text views. Note that it does not handle
 * styled text or right-to-left writing systems.
 *
 */
public class JoystickView extends View {
    
    private float mTouchStartX;
    private float mTouchStartY;
    private float mTouchCurrX;
    private float mTouchCurrY;
    
    
    private Paint[] mPaints;
    private Paint mFramePaint;
    private boolean[] mUseCenters;
    private RectF[] mOvals;
    private float mStart;

	private float moveJoystickX;
	private float moveJoystickY;
	private float radius;
    
    private static final float SWEEP_INC = 2;
    private static final float START_INC = 15;
    
    /**
     * Constructor.  This version is only needed if you will be instantiating
     * the object manually (not from a layout XML file).
     * @param context
     */
    public JoystickView(Context context) {
        super(context);
        initView();
    }

	/**
     * Construct object, initializing with any attributes we understand from a
     * layout file. These attributes are defined in
     * SDK/assets/res/any/classes.xml.
     * 
     * @see android.view.View#View(android.content.Context, android.util.AttributeSet)
     */
    public JoystickView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
        
        /*
        mPaint = new Paint();
        //mPaint.setColor(0x88888888);
        
        mOval = new RectF(250,720, 
        		310, 
        		780);
        requestLayout();
        invalidate();

        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.LabelView);

        CharSequence s = a.getString(R.styleable.LabelView_text);
        if (s != null) {
            setText(s.toString());
        }

        // Retrieve the color(s) to be used for this view and apply them.
        // Note, if you only care about supporting a single color, that you
        // can instead call a.getColor() and pass that to setTextColor().
        setTextColor(a.getColor(R.styleable.LabelView_textColor, 0xFF000000));

        int textSize = a.getDimensionPixelOffset(R.styleable.LabelView_textSize, 0);
        if (textSize > 0) {
            setTextSize(textSize);
        }

        a.recycle();
        */
        setText("test");
        
    }

    private final void initView() {
         
         mPaints = new Paint[4];
         mUseCenters = new boolean[4];
         mOvals = new RectF[4];
 
         mPaints[0] = new Paint();
         mPaints[0].setAntiAlias(true);
         mPaints[0].setStyle(Paint.Style.FILL);
         mPaints[0].setColor(0x88FF0000);
         mUseCenters[0] = false;
         
         mPaints[1] = new Paint(mPaints[0]);
         mPaints[1].setColor(0x8800FF00);
         mUseCenters[1] = true;
         
         mPaints[2] = new Paint(mPaints[0]);
         mPaints[2].setStyle(Paint.Style.STROKE);
         mPaints[2].setStrokeWidth(8);
         mPaints[2].setColor(0x880000FF);
         mUseCenters[2] = false;

         mPaints[3] = new Paint(mPaints[2]);
         mPaints[3].setColor(0x88888888);
         mUseCenters[3] = true;
         
         
         mOvals[0] = new RectF( 10, 270,  70, 330);
         mOvals[1] = new RectF( 90, 270, 150, 330);
         mOvals[2] = new RectF(170, 270, 230, 330);
         mOvals[3] = new RectF(60, 60, 160, 160);
         
         mFramePaint = new Paint();
         mFramePaint.setAntiAlias(true);
         mFramePaint.setStyle(Paint.Style.STROKE);
         mFramePaint.setStrokeWidth(0);
    }

    /**
     * Sets the text to display in this label
     * @param text The text to display. This will be drawn as one line.
     */
    
    public void setText(String text) {
        //mText = text;
        requestLayout();
        invalidate();
    }
    
    private void drawArcs(Canvas canvas, RectF oval, boolean useCenter,
            Paint paint) {
    	canvas.drawArc(oval, mStart, 360, useCenter, paint);
}
    /**
     * Sets the text size for this label
     * @param size Font size
     */
    public void setTextSize(int size) {
       // mTextPaint.setTextSize(size);
        requestLayout();
        invalidate();
    }

    /**
     * Sets the text color for this label.
     * @param color ARGB value for the text
     */
    public void setTextColor(int color) {
        //mTextPaint.setColor(color);
        invalidate();
    }

    /**
     * @see android.view.View#measure(int, int)
     */
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec),
                measureHeight(heightMeasureSpec));
    }

    /**
     * Determines the width of this view
     * @param measureSpec A measureSpec packed into an int
     * @return The width of the view, honoring constraints from measureSpec
     */
    
    private int measureWidth(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            // We were told how big to be
            result = specSize;
        } else {
            // Measure the text
            result = (int)100;
            if (specMode == MeasureSpec.AT_MOST) {
                // Respect AT_MOST value if that was what is called for by measureSpec
                result = Math.min(result, specSize);
            }
        }

        return 220;
    }

    /**
     * Determines the height of this view
     * @param measureSpec A measureSpec packed into an int
     * @return The height of the view, honoring constraints from measureSpec
     */
    
    private int measureHeight(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            // We were told how big to be
            result = specSize;
        } else {
            // Measure the text (beware: ascent is a negative number)
            result = (int) 100;
            if (specMode == MeasureSpec.AT_MOST) {
                // Respect AT_MOST value if that was what is called for by measureSpec
                result = Math.min(result, specSize);
            }
        }
        return 220;
    }
    

    /**
     * Render the text
     * 
     * @see android.view.View#onDraw(android.graphics.Canvas)
     */
    
    @Override protected void onDraw(Canvas canvas) {
    	
    	
    	//
    	//
    	//Use MapView and calculate Radius using MapRadius
    	//
    	//
    	
    	radius = calculateRadius(mTouchCurrX - mTouchStartX, mTouchCurrY - mTouchStartY);
    	moveJoystickX = calculateJoystickMove(radius, mTouchCurrX - mTouchStartX);
    	moveJoystickY = calculateJoystickMove(radius, mTouchCurrY - mTouchStartY);
    	
    	canvas.translate(moveJoystickX, moveJoystickY);
        //canvas.drawColor(Color.WHITE);
        drawArcs(canvas, mOvals[3], mUseCenters[3], mPaints[3]);
        invalidate();
    }
    
    private float calculateRadius(float moveX, float moveY) {
		return (float) Math.sqrt(moveX * moveX + moveY * moveY);
	}

	private float calculateJoystickMove(float radius, float move) {
		if (radius > 50 || radius < -50){
			return move * 50 / radius;
		}
		return move;
	}

	@Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mTouchStartX = mTouchCurrX = x;
                mTouchStartY = mTouchCurrY = y;
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                mTouchCurrX = x;
                mTouchCurrY = y;
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
            	mTouchStartX = mTouchCurrX = x;
                mTouchStartY = mTouchCurrY = y;
                invalidate();
                break;
        }
        return true;
    }

	public float getMoveJoystickUp() {
		float moveYRatio = - moveJoystickY / 50;
		return clculateMoveRatio(moveYRatio);
	}

	public float getMoveJoystickDown() {
		float moveYRatio = moveJoystickY / 50;
		return clculateMoveRatio(moveYRatio);
	}
	
	public float getMoveJoystickLeft() {
		float moveXRatio = - moveJoystickX / 50;
		return clculateMoveRatio(moveXRatio);
	}

	public float getMoveJoystickRight() {
		float moveXRatio = moveJoystickX / 50;
		return clculateMoveRatio(moveXRatio);
	}

	private float clculateMoveRatio(float moveYRatio) {
		if(moveYRatio > 0){
			if(moveYRatio < (Math.sqrt(2)/2)){
				return  moveYRatio;
			}
			else{
				return (float) ((Math.sqrt(2)/2));
			}
		}
		else{
			return 0;
		}
	}

    
    /*
    protected class myDragEventListener implements View.OnDragEventListener {

        // This is the method that the system calls when it dispatches a drag event to the
        // listener.
        public boolean onDrag(View v, DragEvent event) {

            // Defines a variable to store the action type for the incoming event
            final int action = event.getAction();

            // Handles each of the expected events
            switch(action) {

                case DragEvent.ACTION_DRAG_STARTED:

                    // Determines if this View can accept the dragged data
                    if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {

                        // As an example of what your application might do,
                        // applies a blue color tint to the View to indicate that it can accept
                        // data.
                        v.setColorFilter(Color.BLUE);

                        // Invalidate the view to force a redraw in the new tint
                        v.invalidate();

                        // returns true to indicate that the View can accept the dragged data.
                        return(true);

                        } else {

                        // Returns false. During the current drag and drop operation, this View will
                        // not receive events again until ACTION_DRAG_ENDED is sent.
                        return(false);

                        }
                    break;

                case DragEvent.ACTION_DRAG_ENTERED: {

                    // Applies a green tint to the View. Return true; the return value is ignored.

                    v.setColorFilter(Color.GREEN);

                    // Invalidate the view to force a redraw in the new tint
                    v.invalidate();

                    return(true);

                    break;

                    case DragEvent.ACTION_DRAG_LOCATION:

                    // Ignore the event
                        return(true);

                    break;

                    case DragEvent.ACTION_DRAG_EXITED:

                        // Re-sets the color tint to blue. Returns true; the return value is ignored.
                        v.setColorFilter(Color.BLUE);

                        // Invalidate the view to force a redraw in the new tint
                        v.invalidate();

                        return(true);

                    break;

                    case DragEvent.ACTION_DROP:

                        // Gets the item containing the dragged data
                        ClipData.Item item = event.getClipData().getItemAt(0);

                        // Gets the text data from the item.
                        dragData = item.getText();

                        // Displays a message containing the dragged data.
                        Toast.makeText(this, "Dragged data is " + dragData, Toast.LENGTH_LONG);

                        // Turns off any color tints
                        v.clearColorFilter();

                        // Invalidates the view to force a redraw
                        v.invalidate();

                        // Returns true. DragEvent.getResult() will return true.
                        return(true);

                    break;

                    case DragEvent.ACTION_DRAG_ENDED:

                        // Turns off any color tinting
                        v.clearColorFilter();

                        // Invalidates the view to force a redraw
                        v.invalidate();

                        // Does a getResult(), and displays what happened.
                        if (event.getResult()) {
                            Toast.makeText(this, "The drop was handled.", Toast.LENGTH_LONG);

                        } else {
                            Toast.makeText(this, "The drop didn't work.", Toast.LENGTH_LONG);

                        };

                        // returns true; the value is ignored.
                        return(true);

                    break;

                    // An unknown action type was received.
                    default:
                        Log.e("DragDrop Example","Unknown action type received by OnDragListener.");

                    break;
            };
        };
    };
    */
	
}
